'''DataK _Base protocol

 Defines the abstract base for all DataK protocols.
 You must subclass _Base to create your own protocol.

# LICENSE ....................................................................
    This file is part of DataK.

    DataK is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    DataK is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with DataK.  If not, see <http://www.gnu.org/licenses/>.
# ............................................................................

'''

class _Base:
    '''
    Abstract base for all DataK protocols.
    
    protocols are used by the connection to setup its items.
    The setup_item() method is responsible for this.
    
    Every protocol has a self.user string attribute. Beware that this attribute
    is not yet set during the __init__ execution.
    You can use it in setup_item() to configure some strategies.
    
    Every protocol has a self.config dict attribute. This one is set before the
    __init__ execution.
    
    The docstring of the subclasses must explain the protocol
    and list the keys from self.config used to configure it.
    (This docstring is shown to the user!)
    You should also specify if a re-connection is needed in order to apply
    the option change.
    
    '''
    def __init__( self, config_string='' ):
        '''
        Create the protocol and configure it as described by config_string.
        '''
        self.user = 'unknown_user'
        self.config = {}
        self.set_config( config_string )

    def set_config( self, config_string ):
        '''
        Load config_string in self.config
        Subclass can use self.config in their constructor to alter strategies.
        '''
        if config_string.strip():
            eval "self.config=%s" % config_string

    def config_string( self ):
        '''
        Returns a string describing the configuration of this protocol.
        Subclass must provide something suitable for their __init__. 
        '''
        if self.config != {}:
            return repr( self.config )
        return ''

    def set_option( self, option_name, option_value ):
        '''
        Changes the value on option_name key in self.config
        Some protocols may not handle changing some option
        at runtime. They must indicate it clearly in the class
        docstring in such case.
        
        Both option_name and option_value must be string.
        
        '''
        self.config[option_name] = option_value
    
    def _option_changed( self, option_name ):
        '''
        Called when self.congig as been edited by self.set_option().
        
        Protocol supporting some runtime configuration must override
        this to handle the new option_value.
        
        See self.set_option().
        '''
        pass
        
    def setup_item( self, item ):
        '''
        Configure the item's strategies.
        Your protocol must use the appropriate instance variables
        to store the strategies in the item:
            item._rc        the revision control startegy
            item._attrs     the attribute access strategy
            item._selecter  the select strategies
            item._sorter    the sort strategy
            item._grouper   the grouping strategy

        Note that unless you're doing strange things, your protocol
        should set a different attribute access strategy on item.Item, 
        item.Link and item.Group, as well as a different select strategies
        on item.Item/item.Link and item.Group.
        '''
        raise NotImplementedError()


